home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PRUS101 / FSWAP.ASM < prev    next >
Assembly Source File  |  1994-09-15  |  24KB  |  705 lines

  1. TITLE FSWAP.ASM
  2. ; (***************************************************************************
  3. ;
  4. ;           RELEASE 1.00 - as contained in the file
  5. ;               by Peter Holschbach, 2:2450/660.3, GERMANY
  6. ;
  7. ;              --------------------------------------------
  8. ;               organized for Fido's PASCAL related echoes
  9. ;              --------------------------------------------
  10. ;
  11. ;    09/01/1994 to --/--/---- by Peter Holschbach, 2:2450/660.3,  GERMANY
  12. ;
  13. ;
  14. ;          As far as third party copyrights are not violated this
  15. ;          source code is hereby placed to the public domain. Use
  16. ;          it whatever way you want, but use AT YOUR OWN RISK.
  17. ;
  18. ;          In case you should modify the source rather send your
  19. ;          modifications to the unit's current organizer (see above for
  20. ;          NM address) than to spread it on your own. This will help to
  21. ;          keep the unit updated and grant a certain standard to all
  22. ;          other users as well.
  23. ;
  24. ;          The unit is currently still under work. So it might greatly
  25. ;          benefit of your participation.
  26. ;
  27. ;          Those who contributed to the following piece of source,
  28. ;          listed in alphabethical order:
  29. ;       ================================================================
  30. ;          Peter Holschbach ...
  31. ;       ================================================================
  32. ;          YOUR NAME WILL APPEAR HERE IF YOU CONTRIBUTE USEFUL SOURCE.
  33. ;
  34. ;          Credits in your own programs are as welcome as unnecessary.
  35. ;
  36. ;***************************************************************************)
  37. ;
  38. ; Assembler:  tested only with TASM 3.2
  39. ; Call:       TASM /M3 FSWAP.ASM
  40. ;
  41. ;***************************************************************************)
  42.  
  43. .8086           ; OK! the last PC at the world should use it
  44. JUMPS           ; use long jumps if needed
  45. LOCALS @@       ; every label started with @@ is local
  46.  
  47. ;-----------------------------------------------------------------------------
  48.  
  49. PUBLIC          SwapExec
  50.  
  51. ;-----------------------------------------------------------------------------
  52.  
  53. EXTRN DosRetValue  : Word     ; global variable for return value
  54. EXTRN PrefixSeg    : Word
  55. EXTRN SwapFilePath : Byte     ; it's a string
  56.  
  57. ;-----------------------------------------------------------------------------
  58.  
  59. DosBlockSize EQU   0FFF0H     ; there are problems to write FFFFh,
  60.                               ; max. FFFAh Bytes will be written.
  61.                               ; ! use ony a size MOD 16 !
  62.  
  63. IF (DosBlockSize MOD 16) NE 0
  64.   ERR "The size of DosBlockSize should be a value MOD 16 !"
  65. ENDIF
  66.  
  67. EmsPageSize EQU 16 * 1024
  68.  
  69. ;-------------------------- error messages from "SwapExec"
  70.  
  71. ErrDeviceNotAvailable    EQU   0001        ; EMS/XMS not available
  72. ErrSizeCalc              EQU   0002        ; start is bigger then last
  73. ErrNotEnoughSpace        EQU   0003        ; EMS/XMS/Disk
  74. ErrCantGetSize           EQU   0004        ; Disk
  75. ErrCreateTempFile        EQU   0005        ; Disk
  76. ErrWriteFile             EQU   0006        ; Disk
  77. ErrReadFile              EQU   0007        ; Disk
  78. ErrCheckSizeToSave       EQU   0008
  79. ErrAllocation            EQU   0009
  80. ErrSwapOut               EQU   0010
  81.  
  82. ; MSB
  83.  
  84. ErrMemReduce             EQU   11       ; -> LSB = error from DOS
  85. ErrManager               EQU   0FFh     ; -> MSB = error message from XMS/EMS
  86.  
  87. ;-------------------------- definitions for easy acces
  88.  
  89. hi                    EQU   (Word PTR 2)
  90. lo                    EQU   (Word PTR 0)
  91.  
  92. ofst                  EQU   (Word PTR 0)
  93. segm                  EQU   (Word PTR 2)
  94.  
  95. hidden                EQU   2
  96. sys                   EQU   4
  97. SwapFileAttr          EQU   hidden+sys
  98.  
  99. ;-----------------------------------------------------------------------------
  100. ; The definitoins of some structures
  101. ;-----------------------------------------------------------------------------
  102.  
  103.               ; ----------- structur to copy data from/to EMS
  104. EMSstrucTyp STRUC
  105.   RegionLength         DD  ?   ; length of memory region to copy (in byte)
  106.  
  107.   SourceMemoryTyp      DB  ?   ; 0=conventional memory / 1=EMS
  108.   SourceHandle         DW  ?   ; 0=conventional memory
  109.   SourceInitialOffset  DW  ?   ; offset in source from which to begin
  110.   SourceInitialSegPage DW  ?   ; segment in source from which to begin
  111.  
  112.   DestMemoryTyp        DB  ?   ; 0=conventional memory / 1=EMS
  113.   DestHandle           DW  ?   ; 0=conventional memory
  114.   DestInitialOffset    DW  ?   ; offset in destination from which to begin
  115.   DestInitialSegPage   DW  ?   ; segment in destination from which to begin
  116. ENDS
  117.               ; ----------- structure for exec
  118.  
  119. ExexStrucTyp   STRUC
  120.   EnvironmSeg    DW      ?      ; 0 = copy parent Environment
  121.   ParamString    DD      ?      ; max. 128 Bytes
  122.   FCB1           DD      ?
  123.   FCB2           DD      ?
  124. ENDS
  125.  
  126.               ; ----------- structur to copy data from/to XMS
  127. XMSstrucTyp STRUC
  128.   BytesToMove    DD     ?       ; how many bytes to move
  129.   HandleS        DW     ?       ; if source = XMS the handle number
  130.   PtrS           DD     ?       ; if source = Memory a Pointer at the beginning
  131.   HandleD        DW     ?       ; if destination = XMS the handle number
  132.   PtrD           DD     ?       ; if dest. = memory a Pointer at the beginning
  133. ENDS
  134.  
  135.  
  136. ;-----------------------------------------------------------------------------
  137. ; The definitions of some macros
  138. ;-----------------------------------------------------------------------------
  139.  
  140.      ; --------- simple case macro to CALL depending of a value in AL
  141.  
  142. Case MACRO CaseVar,destinations,OkAddr
  143.      LOCAL @@endcase
  144.      count = 0
  145.  
  146.      MOV   AL,CaseVar
  147.      IRP   jumpTo,destinations,OkAddr
  148.         LOCAL @@J&count
  149.         CMP   AL,count
  150.         JNE   @@J&count
  151.         CALL  jumpTo
  152.         JNC   OkAddr
  153.         JMP   @@endcase
  154.   @@J&count:
  155.         count = count + 1
  156.      ENDM
  157.   @@endcase:
  158. ENDM
  159.  
  160.      ; --------- copy a pascal string in CS and use "0" as terminator
  161.  
  162. CopyPascalString MACRO Source,Destination
  163. LOCAL @@emptyString
  164.          PUSH    DS
  165.          LDS     SI,Source
  166.  
  167.          MOV     AX,SEG Destination
  168.          MOV     ES,AX
  169.          LEA     DI,Destination
  170.  
  171.          LODSB                  ; size of string in AL
  172.          CMP     AL,0           ; empty string ?
  173.          JE      @@emptyString
  174.          MOV     CL,AL
  175.          XOR     CH,CH          ; CX = size
  176.          REP_FastMovs
  177. @@emptyString:
  178.          XOR     AL,AL
  179.          STOSB
  180.          POP     DS
  181. ENDM
  182.  
  183.      ; --------- macro to use MOVSW
  184.  
  185. REP_FastMovs MACRO
  186. LOCAL  @@noByteLeft
  187.          SHR     CX,1
  188.          REP     MOVSW
  189.          JNC     @@noByteLeft
  190.          MOVSB
  191. @@noByteLeft:
  192.  
  193. ENDM
  194.  
  195. ;##########################################################################
  196. ; and now the first code
  197. ;##########################################################################
  198.  
  199. .MODEL  LARGE
  200. .CODE
  201.  
  202. ;--------------------------------------------------
  203. ; All variables in CS who are needed after swap out
  204. ;--------------------------------------------------
  205.  
  206.    ;-------- variables needed for EMS
  207.  
  208. EMSmovStruc    EMSstrucTyp ?
  209.  
  210.    ;--------  variables used for XMS
  211.  
  212. XMSPointer      DD ?
  213.  
  214.    ;-------- variables for exec
  215.  
  216. ProgPathName    DB 80  DUP (?)
  217.  
  218. ProgParam       DB 128 DUP (?)
  219. nFCB1           DB 16 DUP (?)
  220. nFCB2           DB 16 DUP (?)
  221.  
  222. ExexStruc       ExexStrucTyp {EnvironmSeg=0, ParamString=ProgParam,FCB1=nFCB1,FCB2=nFCB2}
  223.  
  224.    ;----------------
  225.  
  226. myPSP           DW   ?
  227. MaxSize         DW   ?                  ; aktual size of the program
  228. MinSize         DW   ?                  ; the minimal size of this program
  229.                                         ; in paragraphs
  230.    ;----------------
  231.  
  232. EnAdress        DD ?                    ; last Adress to save
  233. Handle          DW ?                    ; then Handle for DISC/EMS/XMS
  234.  
  235. MethodCS        DB ?
  236.  
  237. RetValue        DW ?
  238. SaveSize        DD ?
  239.  
  240.    ;--------  everything for the stack
  241.  
  242. SaveSP          DW ?
  243. SaveSS          DW ?
  244.  
  245. OriginSP        DW ?
  246. OriginSS        DW ?
  247.  
  248.                 DW 50 DUP (?)
  249. TmpStack        LABEL WORD
  250.  
  251.  
  252. ;----------------------------------------------------------------------------
  253. ; the function that must be called from Turbo Pascal
  254. ;----------------------------------------------------------------------------
  255. ;Function SwapExec (FileName,Parameter : String; LastAdr : Pointer; Method : TSwapMemTyp): Word;
  256.  
  257. SwapExec        PROC    PASCAL FAR FileName : DWORD,Parameter : DWORD, LastAdr : DWord, Method : Byte
  258.  
  259.                 PUSH    DS                      ; save the datasegment
  260.  
  261.                 CALL    CopyFromTurbo
  262.                 MOV     AX,ErrCheckSizeToSave   ; nothing to save ?
  263.                 JE      Exit1
  264.  
  265.                 ;--------------- check if memorytyp is available
  266.  
  267.                 CASE    MethodCS,<CheckXMSDriver,CheckEMSDriver,CheckDiskDriver>,DeviceOK
  268.  
  269.                 ; -------------- errorhandler "device not available"
  270. DeviceError:
  271.  
  272.                 MOV     AX,ErrDeviceNotAvailable
  273.                 JMP     Exit1
  274. DeviceOK:
  275.                 ;--------------- allocate memory
  276.  
  277.                 CASE    MethodCS,<XMSAllocate,EMSAllocate,DiskAllocate>,AlloCationOk
  278.  
  279.                 ;--------------- allocation error
  280. AllocationError:
  281.                 MOV     AX,ErrAllocation
  282.                 JMP     Exit1
  283.  
  284.                 ;--------------- swap to memory or disk
  285. AlloCationOk:
  286.                 MOV     Handle,DX       ; save the handle
  287.  
  288.                 CASE    MethodCS,<SwapXms,SwapEMS,SwapDisk>,SwapOk
  289.                 JMP     Exit1
  290.  
  291. swapError:
  292.                 ;--------------- problem while swapout
  293.  
  294.                 CASE    MethodCS,<XMSDeAllocate,EMSDeAllocate,DiskDeAllocate>,ProbDealloc
  295.  
  296.                 ; ignore any error
  297. ProbDealloc:
  298.                 MOV     AX,ErrSwapOut
  299.                 JMP     Exit1;
  300.  
  301. SwapOk:
  302.                 ;--------------- save origin stack and switch to temporary stack
  303.  
  304.                 MOV     OriginSP,SP
  305.                 MOV     AX,SS
  306.                 MOV     OriginSS,AX             ; save origin stack
  307.                 MOV     AX,SEG TmpStack
  308.                 MOV     SS,AX                   ; interrupt will be disabled
  309.                                                 ; for the next command
  310.                 LEA     SP,TmpStack             ; use stack in codesegment
  311.  
  312.                 ; ---------- reduce memory
  313.  
  314.                 MOV     AX,MyPSP
  315.                 MOV     ES,AX                   ; ES = MCB
  316.                 MOV     BX,MinSize
  317.                 MOV     AH,4Ah
  318.                 INT     21h                     ; set memory to new size
  319.                 MOV     AH,AL
  320.                 MOV     AL,ErrMemReduce
  321.                 JNC     reduceOk
  322.  
  323.                 MOV     CX,OriginSS
  324.                 MOV     BX,OriginSP
  325.                 MOV     SS,CX
  326.                 MOV     SP,BX
  327.                 JMP     Exit1
  328.  
  329. reduceOk:
  330.                 ; ---------- exec
  331.  
  332.                 PUSH    DS
  333.                 PUSH    BP              ; save it for TurboPasal
  334.  
  335.                 PUSH    CS
  336.                 POP     DS
  337.                 PUSH    CS
  338.                 POP     ES              ; DS = ES = CS
  339.  
  340.                 LEA     SI,ProgPathName
  341.                 LEA     DI,nFCB1
  342.                 MOV     AX,2901h
  343.                 INT     21h
  344.  
  345.                 LEA     DI,nFCB2
  346.                 MOV     AX,2901h
  347.                 INT     21h
  348.  
  349.                 LEA     BX,ExexStruc
  350.                 LEA     DX,ProgPathName
  351.                 MOV     SaveSP,SP       ; some DOS versions use ist
  352.                 MOV     SaveSS,SS       ; without restoring it
  353.                 CLD                     ; some DOS versions need this !
  354.                 MOV     AX,4B00h
  355.                 INT     21h
  356.                 MOV     SS,SaveSS       ; disable interrupt ! until
  357.                 MOV     SP,SaveSP       ; next command
  358.                 JC      ExecErr
  359.                 XOR     AX,AX
  360. ExecErr:
  361.                 POP     BP
  362.                 POP     DS
  363.                 MOV     RetValue,AX
  364.  
  365.                 ; ---------- expand memory
  366.  
  367.                 MOV     AX,MyPSP
  368.                 MOV     ES,AX
  369.                 MOV     BX,MaxSize
  370.                 MOV     AH,4Ah
  371.                 INT     21h
  372.                 JNC     ExpandOk
  373.  
  374.                 ; --- error -> no rescue
  375.  
  376.                 MOV     AX,4CFFh  ; terminate process
  377.                 INT     21h
  378.  
  379. ExpandOk:
  380.  
  381.                 CASE    MethodCS,<SwapInXms,SwapInEMS,SwapInDisk>,isSwapIn
  382. swapInError:
  383.                 MOV     AX,4CFFh  ; terminate process
  384.                 INT     21h
  385.  
  386. isSwapIn:
  387.                 MOV     AX,RetValue
  388.                 MOV     DosRetValue,AX
  389.                 MOV     CX,AX                   ; save return value
  390.                 MOV     AX,OriginSS
  391.                 MOV     BX,OriginSP
  392.                 MOV     SS,AX
  393.                 MOV     SP,BX
  394.  
  395.                 CASE    MethodCS,<XMSDeAllocate,EMSDeAllocate,DiskDeAllocate>,isDeAllocated
  396.                 JMP     EXIT1
  397. deAllocError:
  398.  
  399. isDeAllocated:
  400.                 MOV     AX,0
  401.  
  402. Exit1:          ;--------------- clear only the stack and exit
  403.                 POP     DS
  404.                 RET
  405.  
  406. ENDP
  407.  
  408. ;--------------------------------------------------------------------------
  409. ;--------------------------------------------------------------------------
  410.  
  411. SwapInDisk PROC
  412.                 PUSH    DS
  413.  
  414.                 ; ---------------- set write pointer to beginning of file
  415.                 MOV     AX,4200h        ; move file pointer, from start of file
  416.                 MOV     BX,Handle       ; Handle number
  417.                 MOV     CX,0
  418.                 MOV     DX,0            ; Offset = 0
  419.                 INT     21h
  420.  
  421.                 ; --------------- prepare reading
  422.  
  423.                 LES     DI,SaveSize     ; ES,DI = Size to save
  424.  
  425.                 MOV     DX,OFFSET SavePoint
  426.                 MOV     AX,SEG SavePoint
  427.                 MOV     DS,AX           ; DS,DX = pointer at start
  428.  
  429.                 ; --------------- read from disk
  430. @@readLoop:
  431.                 MOV     BX,Handle       ; Handle number
  432.                 MOV     CX,DosBlockSize ; read max. blocksize
  433.                 MOV     AX,ES
  434.                 CMP     AX,0            ; less then 64k to read ?
  435.                 JNE     @@savemax       ; no -> full size
  436.                 CMP     DI,DosBlockSize
  437.                 JNB     @@savemax       ; if there is more then one block
  438.                 MOV     CX,DI           ; save the rest
  439. @@savemax:
  440.                 MOV     AH,3Fh          ; read from a file
  441.                 PUSH    DX
  442.                 PUSH    ES
  443.                 PUSH    DI
  444.                 INT     21h
  445.                 POP     DI
  446.                 POP     ES
  447.                 POP     DX
  448.                 JC      @@readErr       ; error during reading ?
  449.                 CMP     AX,CX           ; check if all bytes are read
  450.                 JNE     @@readErr       ; error during reading ?
  451.                 SUB     DI,AX           ; size to save = size to save - saved
  452.                 MOV     AX,ES
  453.                 SBB     AX,0
  454.                 MOV     ES,AX           ; ES,DI = ES,DI - CX = size to read
  455.  
  456.                 ADD     AX,DI           ; ES+DI = 0 -> nothing left to read
  457.                 CMP     AX,0
  458.                 JE      @@ready
  459.  
  460.                 MOV     AX,DS
  461.                 ADD     AX,DosBlockSize/16 ; next Segment to read
  462.                 MOV     DS,AX
  463.                 JMP     @@readloop
  464. @@ready:
  465.                 POP     DS
  466.                 MOV     AH,3Eh          ; close handle
  467.                 INT     21h
  468.                 CLC
  469.                 RET
  470.  
  471. @@readErr:
  472.                 ; if a error occures, the program must be stopped
  473.  
  474.                 MOV     AX,4CFFh  ; terminate process
  475.                 INT     21h
  476. ENDP
  477.  
  478. ;--------------------------------------------------------------------------
  479.  
  480. SwapInEMS PROC
  481.                 PUSH    DS              ; save Turbo's DS
  482.                 PUSH    CS
  483.                 POP     DS
  484.                 PUSH    CS
  485.                 POP     ES              ; DS = ES = CS
  486.  
  487.                 LEA     SI,SaveSize
  488.                 LEA     DI,EMSmovStruc.RegionLength
  489.                 MOVSW
  490.                 MOVSW                   ; copy the length
  491.  
  492.                 MOV     AL,1
  493.                 STOSB                   ; copy from EMS
  494.                 MOV     AX,Handle
  495.                 STOSW
  496.                 XOR     AX,AX
  497.                 STOSW
  498.                 STOSW
  499.  
  500.                 XOR     AX,AX
  501.                 STOSB                   ; dest memory type = conventional
  502.                 STOSW                   ; handle = 0
  503.                 MOV     AX,OFFSET SavePoint
  504.                 STOSW
  505.                 MOV     AX,SEG SavePoint
  506.                 STOSW                   ; start from "SavePoint"
  507.  
  508.                 LEA     SI,EMSmovStruc.RegionLength
  509.                 MOV     AX,5700h
  510.                 INT     67h
  511.                 POP     DS
  512.                 OR      AH,AH
  513.                 JNZ     @@EMSerror
  514.                 RET
  515. @@EMSerror:
  516.                 ; if a error occures, the program must be stopped
  517.  
  518.                 MOV     AX,4CFFh  ; terminate process
  519.                 INT     21h
  520. ENDP
  521.  
  522. ;--------------------------------------------------------------------------
  523.  
  524. SwapInXMS PROC
  525.                 PUSH    DS              ; save DS from Turbo Pascal
  526.                 MOV     AX,CS
  527.                 MOV     DS,AX           ; DS = CS
  528.                 MOV     ES,AX           ; ES = CS
  529.                 CLD
  530.                 LEA     DI,XMSStructur  ; CS:DI = Pointer ad XMS structure
  531.                 LEA     SI,SaveSize     ; CS:SI = memory we use
  532.                 MOVSW                   ; save size
  533.                 MOVSW                   ;    in structure
  534.                 MOV     AX,Handle
  535.                 STOSW                   ; source handle <> 0 -> XMS
  536.                 XOR     AX,AX
  537.                 STOSW
  538.                 STOSW                   ; offset source = 0
  539.  
  540.                 STOSW                   ; handle destination = 0
  541.                 MOV     AX,OFFSET SavePoint
  542.                 STOSW
  543.                 MOV     AX,SEG SavePoint
  544.                 STOSW                   ; start adress
  545.  
  546.                 MOV     AH,0Bh          ; XMS : "copy block"
  547.                 LEA     SI,XMSStructur  ; DS:SI = pointer at structure
  548.                 CALL    XmsPointer      ; XMS Call
  549.                 POP     DS
  550.                 CMP     AX,1            ; CY = 0 if equal
  551.                 JNE     @@XMSerror
  552.                 RET
  553. @@XMSerror:
  554.                 ; if a error occures, the program must be stopped
  555.  
  556.                 MOV     AX,4CFFh  ; terminate process
  557.                 INT     21h
  558. ENDP
  559.  
  560. ;--------------------------------------------------------------------------
  561.  
  562. EVEN
  563. SavePoint:    ; *******  First point to save **********
  564.  
  565. ;--------------------------------------------------------------------------
  566.  
  567.  
  568. ; -----------------------------------------
  569. ; Variables who are not nedded for swap in
  570. ; -----------------------------------------
  571.  
  572.    ;--------  variables used for DISK
  573.  
  574. TmpName         DB 256 DUP (?)
  575.  
  576.    ;-------  variables used for EMS
  577.    EVEN
  578.  
  579. EMSDeviceName:  DB 'EMMXXXX0'
  580.  
  581.    ;-------- variables used for XMS
  582.  
  583. XMSStructur     XMSstrucTyp  ?
  584.  
  585. ; ----------------------------------------------------------------------------
  586. ; All functions who are not uses while/after swap out
  587. ; ----------------------------------------------------------------------------
  588.  
  589. ;-----------------------------------------------------------------------------
  590. ; calculate the bytes to save
  591. ;-----------------------------------------------------------------------------
  592.  
  593. BytesToSave PROC
  594.  
  595.                 MOV      AX,CS
  596.                 MOV      BX,10h
  597.                 MUL      BX
  598.                 LEA      BX,SavePoint
  599.                 ADD      AX,BX
  600.                 ADC      DX,0            ; DX,AX = first adress to save
  601.  
  602.                 PUSH     DX
  603.                 PUSH     AX
  604.  
  605.                 MOV      AX,ES            ; AX:CX = last adress as pointer
  606.                 MOV      BX,10H
  607.                 MUL      BX
  608.                 ADD      AX,CX
  609.                 ADC      DX,0             ; DX,AX = last adress as 32 Bit adress
  610.  
  611.                 POP      BX
  612.                 POP      CX               ; CX,BX = first adress as 32 Bit
  613.  
  614.                 SUB      AX,BX
  615.                 SBB      DX,CX            ; DX,AX = Size
  616.  
  617.                 RET
  618.  
  619. CalcErr:        MOV     AX,0
  620.                 MOV     DX,0
  621.                 RET
  622.  
  623. ENDP
  624.  
  625.  
  626. ;-----------------------------------------------------------------------------
  627. ; Copy data from variables in DS to variables in CS and calculate
  628. ;-----------------------------------------------------------------------------
  629.  
  630. CopyFromTurbo PROC
  631.                  MOV     AL,Method
  632.                  MOV     MethodCS,AL
  633.  
  634.                  CopyPascalString FileName,ProgPathName   ; copy program name in CS
  635.  
  636.                ; copy parameters into code segment
  637.  
  638.                  PUSH    DS
  639.                  LDS     SI,Parameter   ; DS:SI -> pointer at parameter
  640.  
  641.                  MOV     AX,SEG ProgParam
  642.                  MOV     ES,AX
  643.                  LEA     DI,ProgParam   ; ES:DI -> pointer at code segment
  644.  
  645.                  LODSB                  ; size of string in AL
  646.                  STOSB                  ; copy to CS
  647.                  CMP     AL,0           ; empty string ?
  648.                  JE      @@emptyString
  649.                  MOV     CL,AL
  650.                  XOR     CH,CH          ; CX = size
  651.                  REP_FastMovs           ; copy string from DS to CS
  652. @@emptyString:
  653.                  MOV     AL,0Dh         ; = CR
  654.                  STOSB                  ; last char must be a CR
  655.                  POP     DS             ; the old DS
  656.  
  657.                  MOV     AX,PrefixSeg   ; get PSP
  658.                  MOV     MyPSP,AX       ;    and save it in CS
  659.  
  660.                  DEC     AX                             ; the MCB
  661.                  MOV     ES,AX                          ; ES = MCB
  662.                  MOV     AX,ES:[0003h]                  ; AX = paragraphs owned now
  663.                  MOV     MaxSize,AX                     ; save this origin size
  664.  
  665.                  ; ---- calculate the programs size after swap out
  666.  
  667.                  ; sP = adress "SavePoint"
  668.                  ; size in byte = OFF (sP) + SEG (sP)*16 - SEG (PSP)*16
  669.                  ; size in parag.= OFF (sP) / 16 + SEG (sP) - SEG (PSP)
  670.                  ; allway round up !
  671.                  ; size in parag.= OFF (sP + 15) / 16 + SEG (sP) - SEG (PSP)
  672.  
  673.                  MOV     AX,OFFSET (SavePoint+15)       ;
  674.                  MOV     CL,4
  675.                  SHR     AX,CL                          ; AX = AX / 16
  676.  
  677.                  ADD     AX,SEG SavePoint
  678.                  SUB     AX,MyPSP                       ; AX = min paragraphs
  679.                  MOV     MinSize,AX
  680.  
  681.                  ; ------ calculate the size needed to swap out
  682.                  ; ------ must been the last in this function !!!!
  683.  
  684.                  LES     CX,[LastAdr]           ; ES:CX = last adress to save
  685.                  MOV     EnAdress.Segm,ES
  686.                  MOV     EnAdress.Ofst,CX
  687.                  CALL    BytesToSave            ; returns in DX,AX size
  688.                  MOV     SaveSize.lo,AX
  689.                  MOV     SaveSize.hi,DX
  690.                  ADD     DX,AX
  691.                  CMP     DX,0                   ; size = 0 = error !
  692.  
  693.                  RET
  694. ENDP
  695.  
  696. ;-----------------------------------------------------------------------------
  697.  
  698. INCLUDE FSWAP.INC
  699.  
  700. ;-----------------------------------------------------------------------------
  701.  
  702.  
  703. END
  704.  
  705.